<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" />
<base href="../" />

<!-- oktavia -->
<link rel="stylesheet" href="assets/searchstyle.css" type="text/css" />
<script src="search/jquery-1.9.1.min.js"></script>
<script src="search/oktavia-jquery-ui.js"></script>
<script src="search/oktavia-english-search.js"></script>
<!-- /oktavia -->

<link rel="stylesheet" href="assets/style.css" type="text/css" />

<title>Access Control - Configure - H2O - the optimized HTTP/2 server</title>
</head>
<body>
<div id="body">
<div id="top">

<h1>
<a href="index.html">H2O</a>
</h1>
<p class="description">the optimized HTTP/1.x, HTTP/2 server</p>

<!-- oktavia -->
<form id="searchform">
<input class="search" type="search" name="search" id="search" results="5" value="" placeholder="Search" />
<div id="searchresult_box">
<div id="close_search_box">&times;</div>
<div id="searchresult_summary"></div>
<div id="searchresult"></div>
<div id="searchresult_nav"></div>
<span class="pr">Powered by <a href="https://github.com/shibukawa/oktavia">Oktavia</a></span>
</div>
</form>
<!-- /oktavia -->

</div>

<table id="menu">
<tr>
<td><a href="index.html">Top</a></td>
<td><a href="install.html">Install</a></td>
<td class="selected"><a href="configure.html">Configure</a></td>
<td><a href="faq.html">FAQ</a></td>
<td><a href="http://blog.kazuhooku.com/search/label/H2O" target="_blank">Blog</a></td>
<td><a href="http://github.com/h2o/h2o/" target="_blank">Source</a></td>
</tr>
</table>

<div id="main">

<h2>
<a href="configure.html">Configure</a> &gt;
Access Control
</h2>


<p>
Starting from version 2.1, H2O comes with a DSL-like mruby library which makes it easy to write access control list (ACL).
</p>

<h2 id="example" class="section-head">Example</h2>

<p>
Below example uses this Access Control feature to write various access control.
</p>

<div class="example">
<div class="caption">Example. Access Control</div>
<pre><code>paths:
  &quot;/&quot;:
    mruby.handler: |
      acl {
        allow { addr == &quot;127.0.0.1&quot; }
        deny { user_agent.match(/curl/i) &amp;&amp; ! addr.start_with?(&quot;192.168.&quot;) }
        respond(503, {}, [&quot;Service Unavailable&quot;]) { addr == malicious_ip }
        redirect(&quot;https://example.com/&quot;, 301) { path =~ /moved/ }
        use Htpasswd.new(&quot;/path/to/.htpasswd&quot;, &quot;realm&quot;) { path.start_with?(&quot;/admin&quot;) }
      }
    file.dir: /path/to/doc_root
</code></pre>
</div>


<p>
In the example, the handler you get by calling <code>acl</code> method will do the following:
<ul>
  <li>
    if the remote IP address is exactly equal to "127.0.0.1", the request will be delegated to the next handler (i.e. serve files under /path/to/doc_root) and all following acl settings are ignored
  </li>
  <li>
    otherwise, if the user agent string includes "curl" and the remote IP address doesn't start with "192.168.", this handler immediately returns <code>403 Forbidden</code> response
  </li>
  <li>
    otherwise, if the remote IP address is exactly equal to the <code>malicious_ip</code> variable, this handler immediately returns <code>503 Service Unavailable</code> response
  </li>
  <li>
    otherwise, if the request path matches with the pattern <code>/moved/i</code>, this handler immediately redirects the client to <code>"https://example.com"</code> with <code>301</code> status code
  </li>
  <li>
    otherwise, if the request path starts with <code>/admin</code>, apply Basic Authentication to the request (for details of Basic Authentication, see <a href="configure/basic_auth.html">here</a>).
  </li>
  <li>
    otherwise, the request will be delegated to the next handler (i.e. serve files under /path/to/doc_root)
  </li>

</ul>

<h2 id="acl-methods" class="section-head">ACL Methods</h2>

<p>
An ACL handler is built by calling ACL methods, which can be used like directives.
ACL methods can only be used in <code>acl</code> block.
</p>

<p>
Each ACL method adds a filter to the handler, which checks whether the request matches the provided condition or not.
Every ACL method can be accompanied by a condition block, which should return boolean value. 
</p>

<p>
The filter defined by the method that first matched the accompanying condition gets applied (e.g. response <code>403 Forbidden</code>, redirect to somewhere).
If a condition block is omitted, all requests matches.
If none of the conditions matches the request, the handler returns <code>399</code> and the request will be delegated to the next handler.
</p>

<div id="allow" class="mruby-method-head">
<h3><a href="configure/access_control.html#allow"><code>"allow"</code></a></h3>
</div>

<dl class="mruby-method-desc">
<dt>Description:</dt>
<dd>
<p>
 Adds a filter which delegates the request to the next handler if the request matches the provided condition. 
</p>

<pre><code>allow { ..condition.. }</code></pre>

</dd>
</dl>

<div id="deny" class="mruby-method-head">
<h3><a href="configure/access_control.html#deny"><code>"deny"</code></a></h3>
</div>

<dl class="mruby-method-desc">
<dt>Description:</dt>
<dd>
<p>
 Adds a filter which returns <code>403 Forbidden</code> if the request matches the provided condition. 
</p>

<pre><code>deny { ..condition.. }</code></pre>

</dd>
</dl>

<div id="redirect" class="mruby-method-head">
<h3><a href="configure/access_control.html#redirect"><code>"redirect"</code></a></h3>
</div>

<dl class="mruby-method-desc">
<dt>Description:</dt>
<dd>
<p>
 Adds a filter which redirects the client if the request matches the provided condition. 
</p>

<pre><code>redirect(location, status) { ..condition.. }</code></pre>

</dd>
<dt>Parameters:</dt>
<dd>
<dl class="mruby-method-parameters">
  <dt>location</dt>
  <dd>Location to which the client will be redirected. Required.</dd>
  <dt>status</dt>
  <dd>Status code of the response. Default value: 302</dd>
</dl>
</dd>
</dl>

<div id="respond" class="mruby-method-head">
<h3><a href="configure/access_control.html#respond"><code>"respond"</code></a></h3>
</div>

<dl class="mruby-method-desc">
<dt>Description:</dt>
<dd>
<p>
 Adds a filter which returns arbitrary response if the request matches the provided condition. 
</p>

<pre><code>respond(status, header, body) { ..condition.. }</code></pre>

</dd>
<dt>Parameters:</dt>
<dd>
<dl class="mruby-method-parameters">
  <dt>status</dt>
  <dd>Status code of the response. Required.</dd>
  <dt>header</dt>
  <dd>Header key-value pairs of the response. Default value: {}</dd>
  <dt>body</dt>
  <dd>Body array of the response. Default value: []</dd>
</dl>
</dd>
</dl>

<div id="use" class="mruby-method-head">
<h3><a href="configure/access_control.html#use"><code>"use"</code></a></h3>
</div>

<dl class="mruby-method-desc">
<dt>Description:</dt>
<dd>
<p>
 Adds a filter which applies the provided handler (callable object) if the request matches the provided condition. 
</p>

<pre><code>use(proc) { ..condition.. }</code></pre>

</dd>
<dt>Parameters:</dt>
<dd>
<dl class="mruby-method-parameters">
  <dt>proc</dt>
  <dd>Callable object that should be applied</dd>
</dl>
</dd>
</dl>

<h2 id="matching-methods" class="section-head">Matching Methods</h2>

<p>
In a condition block, you can use helpful methods which return particular properties of the request as string values.
Matching methods can only be used in a condition block of the ACL methods.
</p>

<div id="addr" class="mruby-method-head">
<h3><a href="configure/access_control.html#addr"><code>"addr"</code></a></h3>
</div>

<dl class="mruby-method-desc">
<dt>Description:</dt>
<dd>
<p>
 Returns the remote IP address of the request. 
</p>

<pre><code>addr(forwarded)</code></pre>

</dd>
<dt>Parameters:</dt>
<dd>
<dl class="mruby-method-parameters">
  <dt>forwarded</dt>
  <dd>If true, returns the value of X-Forwarded-For header if it exists. Default value: true</dd>
</dl>
</dd>
</dl>

<div id="path" class="mruby-method-head">
<h3><a href="configure/access_control.html#path"><code>"path"</code></a></h3>
</div>

<dl class="mruby-method-desc">
<dt>Description:</dt>
<dd>
<p>
 Returns the requested path string of the request. 
</p>

<pre><code>path()</code></pre>

</dd>
</dl>

<div id="method" class="mruby-method-head">
<h3><a href="configure/access_control.html#method"><code>"method"</code></a></h3>
</div>

<dl class="mruby-method-desc">
<dt>Description:</dt>
<dd>
<p>
 Returns the HTTP method of the request. 
</p>

<pre><code>method()</code></pre>

</dd>
</dl>

<div id="header" class="mruby-method-head">
<h3><a href="configure/access_control.html#header"><code>"header"</code></a></h3>
</div>

<dl class="mruby-method-desc">
<dt>Description:</dt>
<dd>
<p>
 Returns the header value of the request associated with the provided name. 
</p>

<pre><code>header(name)</code></pre>

</dd>
<dt>Parameters:</dt>
<dd>
<dl class="mruby-method-parameters">
  <dt>name</dt>
  <dd>Case-insensitive header name. Required.</dd>
</dl>
</dd>
</dl>

<div id="user_agent" class="mruby-method-head">
<h3><a href="configure/access_control.html#user_agent"><code>"user_agent"</code></a></h3>
</div>

<dl class="mruby-method-desc">
<dt>Description:</dt>
<dd>
<p>
 Shortcut for header("user-agent"). 
</p>

<pre><code>user_agent()</code></pre>

</dd>
</dl>

<h2 id="caution" class="section-head">Caution</h2>

<p>
Several restrictions are introduced to avoid misconfiguration when using <code>acl</code> method.
<ul>
<li><code>acl</code> method can be called only once in each handler configuration</li>
<li>If <code>acl</code> method is used, the handler returned by the configuration directive must be the one returned by the <code>acl</code> method</li>
</ul>
If a configuration violates these restrictions, the server will detect it and refuse to launch with error message.
</p>

<p>
For example, both of the following examples violate the restrictions above, so the server will refuse to start up.
</p>

<div class="example">
<div class="caption">Example. Misconfiguration Example 1</div>
<pre><code>paths:
  &quot;/&quot;:
    mruby.handler: |
      acl {    # this block will be ignored!
        allow { addr == &quot;127.0.0.1&quot; }
      }
      acl {
        deny
      }
    file.dir: /path/to/doc_root
</code></pre>
</div>


<div class="example">
<div class="caption">Example. Misconfiguration Example 2</div>
<pre><code>paths:
  &quot;/&quot;:
    mruby.handler: |
      acl {    # this block will be ignored!
        allow { addr == &quot;127.0.0.1&quot; }
        deny
      }
      proc {|env| [399, {}, []}
    file.dir: /path/to/doc_root
</code></pre>
</div>


<p>
You can correct these like the following:
</p>

<div class="example">
<div class="caption">Example. Valid Configuration Example</div>
<pre><code>paths:
  &quot;/&quot;:
    mruby.handler: |
      acl {
        allow { addr == &quot;127.0.0.1&quot; }
        deny
      }
    file.dir: /path/to/doc_root
</code></pre>
</div>


<h2 id="how-to" class="section-head">How-To</h2>

<h3 id="matching-ip-address-blocks">Matching IP Address Blocks</h3>

<p>
You can match an IP address against predefined list of address blocks using a script named <a href="">trie_addr.rb</a>.
</p>
<p>
Below is an example.
</p>

<div class="example">
<div class="caption">Example. Address Block Matching Example</div>
<pre><code>paths:
  &quot;/&quot;:
    mruby.handler: |
      require &quot;trie_addr.rb&quot;
      trie = TrieAddr.new.add([&quot;192.168.0.0/16&quot;, &quot;172.16.0.0/12&quot;])
      acl {
        allow { trie.match?(addr) }
        deny
      }
    file.dir: /path/to/doc_root
</code></pre>
</div>


<p>
This library currently supports only IPv4 addresses. <code>TrieAddr#match?</code> returns <code>false</code> when it receives an invalid IPv4 address (including an IPv6 address) as an argument..
</p>




</div>
<div id="footer">
<p>
Copyright &copy; 2015-2020 <a href="http://dena.com/intl/">DeNA Co., Ltd.</a> et al.
</p>
</div>
</body>
</html>
